home *** CD-ROM | disk | FTP | other *** search
/ Alles Voor Internet / Tout Pour Internet / alles voor internet.iso / MacInternet™ / Telnet / NCSA / tn3270 2.4d7 source / NCSA⁄BYU TCP⁄IP / userd.c < prev    next >
Text File  |  1991-12-18  |  36KB  |  1,647 lines

  1. /*
  2. *  USER.C
  3. *  Network library interface routines
  4. *  Generally called by the session layer
  5. *
  6. ****************************************************************************
  7. *                                                                          *
  8. *      part of:                                                            *
  9. *      TCP/IP kernel for NCSA Telnet                                       *
  10. *      by Tim Krauskopf                                                    *
  11. *                                                                          *
  12. *      National Center for Supercomputing Applications                     *
  13. *      152 Computing Applications Building                                 *
  14. *      605 E. Springfield Ave.                                             *
  15. *      Champaign, IL  61820                                                *
  16. *                                                                          *
  17. *    Copyright (c) 1987, Board of Trustees of the University of Illinois   *
  18. *                                                                          *
  19. ****************************************************************************
  20. *  Revisions:
  21. *  10/87  Initial source release, Tim Krauskopf
  22. *  2/88  typedef support for other compilers (TK)
  23. *  8/88  Gaige Paulsen - support for MacTCP drivers
  24. *  1/89  TK - conversion to new drivers, minor update for new calling convention
  25. *  6/89  TK - update to MacTCP 1.0 include files and use of GetMyIPAddr()
  26. *
  27. */
  28.  
  29. #include <Dialogs.h>
  30. #include <Devices.h>
  31. #include <Memory.h>
  32. #include <MacTCPCommonTypes.h>
  33. #include <TCPPB.h>
  34. #include <UDPPB.h>
  35.  
  36. #define MASTERDEF 1
  37. #include <stdio.h>
  38. #include <String.h>
  39. #include "protocol.h"
  40. #include "data.h"
  41. #include "configrec.h"
  42. #include "maclook.h"
  43. #include "menu.h"
  44. #include "tools.h"
  45. #include <getmyipaddr.h>
  46.  
  47. int EtherNet = -99;        /* Signify Drivers */
  48.  
  49. #define LOWWATER 600
  50.  
  51. pascal void TCPNotify();
  52. pascal void UDPNotify();
  53. long openComplete();
  54. long closeComplete();
  55. long sendComplete();
  56.  
  57. void tcpquit(OSErr rc);
  58.  
  59. /*
  60.  * UDP Stuff
  61.  */
  62.  
  63. #define    UDPBUFSIZ    (1024*8)
  64. #define    getUPB(x,y,z,a)    (UDPiopb *)getPB(x,y,z,a)
  65.  
  66. typedef struct UDPRec {
  67.     StreamPtr stream;                /* Apple's lovely Stream Pointer */
  68.     char   *buffer;                    /* Where the immovable UDP buffer is */
  69.     uint    port;                    /* Which UDP port to use */
  70.     } UDPRec, *UDPRPtr;
  71.  
  72. UDPRPtr uport[ NPORTS];                /* our wonderful little thingies. */
  73.  
  74. /*
  75.  * TCP Stuff
  76.  */
  77. #define    noError    0
  78. #define TCPBUFSIZ    (1024*8)
  79. #define    MAX_FDS_ELEMS    32
  80. #define    MAX_SWDS_ELEMS    16
  81. #define MAX_FREE_PB        128
  82. #define MAX_FREE_SWDS    64
  83.  
  84. #define    Qcall    true
  85. #define    noQcall    false
  86.  
  87. returnPB(TCPiopb *);
  88.  
  89.  
  90. typedef    struct freeEntry {
  91.     int inuse;                        /* is this being used? */
  92.     Ptr    ptr;                        /* Pointer to the free entry */
  93.     } freeEntry;
  94.     
  95. typedef struct exfds {
  96.     int    inuse;                        /* Is this being used */
  97.     wdsEntry fds;                    /* The real data */
  98.     } exfds;
  99.     
  100. typedef struct StreamRec {
  101.     StreamPtr stream;                /* Apple's lovely Stream Pointer */
  102.     char   *buffer;                    /* Where the immovable TCP buffer is */
  103.     int        push;                    /* TRUE if we should push next data block */
  104.     char   *sbuffer;                /* Where the send buffer is */
  105.     wdsEntry    fds[MAX_FDS_ELEMS];    /* Free Data Structure list */
  106.     exfds    exFDS[MAX_FDS_ELEMS];    /* exFDS entries */
  107.     int        maxFDSused;                /* Max of the FDS's that have been used */
  108.     } StreamRec, *StreamRPtr;
  109.     
  110. short TCPd = 0;                        /* refnum of TCP drivers */
  111.  
  112. StreamRPtr streams[NPORTS];
  113.  
  114. int numPB=0;                        /* Number of PB's ever allocated  (Perf. mon. only ) */
  115. int numSWDS=0;                        /* Number of SWDS's ever alloc'd (PM Only) */
  116.  
  117. freeEntry    freePB[ MAX_FREE_PB];
  118. freeEntry    freeSWDS[ MAX_FREE_SWDS];
  119.  
  120. /**************************************************************************/
  121. wdsEntry *getSWDS
  122.   (
  123.     void
  124.   )
  125. {
  126.     int n=0;
  127.     
  128.     while (freeSWDS[n].inuse &&  n<MAX_FREE_SWDS) n++;
  129.     if (n >= MAX_FREE_SWDS)
  130.         return((wdsEntry *) 0L);
  131.     
  132.     freeSWDS[n].inuse=1;
  133.     if (freeSWDS[n].ptr==0L) {
  134.  
  135.         freeSWDS[n].ptr = NewPtr ( sizeof(wdsEntry) *MAX_SWDS_ELEMS);
  136.         numSWDS++;
  137. /*        sprintf(temp,"New SWDS(%d)",numSWDS);
  138.         putln(temp); */
  139.         }
  140.     return((wdsEntry *) freeSWDS[n].ptr);
  141. }
  142.  
  143. /**************************************************************************/
  144. returnSWDS( wds)
  145. wdsEntry *wds;
  146. {
  147.     int n=0;
  148.     
  149.     while (freeSWDS[n].ptr != wds && n<MAX_FREE_SWDS) n++;
  150.     if (n >= MAX_FREE_SWDS)
  151.         return(-1);
  152.     freeSWDS[n].inuse=0;
  153. }
  154.  
  155.  
  156. /**************************************************************************/
  157. TCPiopb *getPB( driver, call, stream, usernum)
  158. int driver, call, usernum;
  159. unsigned long stream;
  160. {
  161. #pragma unused(usernum)
  162.     TCPiopb *pbp;
  163.     int n=0;
  164.     int i;
  165.     
  166.     while (freePB[n].inuse &&  n<MAX_FREE_PB) n++;
  167.  
  168.  
  169.     if (n >= 100)    /* recycle memory so system doesn't get hammered */
  170.         {
  171.         for (i = 0;i < 100;i++)
  172.             {
  173.             if ((freePB[i].inuse) && !(((TCPiopb *)(freePB[i].ptr))->ioResult) )
  174.                 {
  175.                 returnPB((TCPiopb *)freePB[i].ptr); /* re-use this one */
  176.                 n--;                     /* so there is now one less */
  177.                 }
  178.             }
  179.         }
  180.         
  181.     if (n >= MAX_FREE_PB) return(0L);    /* hammer system */
  182.     
  183.     freePB[n].inuse = 1;                
  184.     if (freePB[n].ptr==0L) {
  185.         
  186.         freePB[n].ptr = NewPtr ( sizeof(TCPiopb)+sizeof(int) );
  187.         numPB++;
  188. /*        sprintf(temp,"New PB(%d)",numPB);
  189.         putln(temp); */
  190.         }
  191.     (Ptr) pbp = freePB[n].ptr;
  192.  
  193.  
  194.     if (!pbp) {
  195.         putln("GETPB failed! panic! ");
  196.         quit();
  197.         }
  198.     
  199.     memset( pbp, '\0', sizeof(TCPiopb)+sizeof(int));    /* Default to all zeros */
  200.     
  201.     pbp->ioCRefNum = driver;
  202.     pbp->tcpStream=stream;
  203.     pbp->csCode = call;
  204.     
  205.     return(pbp);
  206. }
  207.  
  208. /**************************************************************************/
  209. clearPB( pbp, driver, call, stream, usernum)
  210. TCPiopb *pbp;
  211. int driver, call, usernum;
  212. unsigned long stream;
  213. {
  214. #pragma unused(usernum)
  215.     memset( pbp, '\0', sizeof(TCPiopb)+sizeof(int));    /* Default to all zeros */
  216.     
  217.     pbp->ioCRefNum = driver;
  218.     pbp->tcpStream=stream;
  219.     pbp->csCode = call;
  220.     
  221. }
  222.  
  223. returnPB( pbp)
  224. TCPiopb *pbp;
  225. {
  226.     int n=0;
  227.     
  228.     while (freePB[n].ptr != pbp && n<MAX_FREE_PB) n++;
  229.     if (n >= MAX_FREE_PB)
  230.         return(-1);
  231.     freePB[n].inuse=0;
  232.     
  233. }
  234.  
  235. /***************************************************************************/
  236. /*  netread
  237. *   Read from a connection buffer into a user buffer.  
  238. *   Returns number of bytes read, < 0 on error
  239. * NOTE:
  240. *    current version very inefficient, but hopefully works.
  241. */
  242. netread(pnum,buffer,n)
  243.     int pnum,n;
  244.     char *buffer;
  245.     {
  246.     int i;
  247.     StreamRPtr p;
  248.     TCPiopb *pbp;
  249.     int inQ, reqdamt;
  250.     
  251.     if (pnum < 0)            /* check validity */
  252.         return(-2);
  253.  
  254.     if (NULL == (p = streams[pnum]))
  255.         return(-2);
  256.     
  257.     
  258.     pbp=getPB( TCPd, TCPStatus, p->stream, pnum);            /* Make status call */
  259.     if (PBControl((ParmBlkPtr) pbp, noQcall) != noError) {
  260.         putln("TCPStatus failed(read)"); return(-1);
  261.         }
  262. #ifdef DEBUGHEADERS    
  263.     { char temp[100];
  264.         sprintf(temp, "Stat: %x(%d)->%x(%d) <%d,%d,%d> [%d,%d] {%d,%d}",
  265.             (int)pbp->csParam.status.remoteHost,
  266.             (int)pbp->csParam.status.remotePort,
  267.             (int)pbp->csParam.status.localHost,
  268.             (int)pbp->csParam.status.localPort,
  269.             (int)pbp->csParam.status.tosFlags,
  270.             (int)pbp->csParam.status.precedence,
  271.             (int)pbp->csParam.status.connectionState,
  272.             (int)pbp->csParam.status.sendWindow,
  273.             (int)pbp->csParam.status.rcvWindow,
  274.             (int)pbp->csParam.status.amtUnackedData,
  275.             (int)pbp->csParam.status.amtUnreadData);
  276.         putln(temp);
  277.     }
  278. #endif DEBUGHEADERS
  279.     
  280.     if (pbp->csParam.status.connectionState !=8) {
  281.         char temp[50];
  282.         sprintf(temp,"CState: %d is %d",(int)pnum, (int)pbp->csParam.status.connectionState);
  283.         putln(temp);
  284.         return(-1);                              /* Connection not established */
  285.         }
  286.     
  287.     inQ = pbp->csParam.status.amtUnreadData;
  288.     reqdamt = n >inQ ? inQ : n;
  289.     
  290.     clearPB( pbp, TCPd, TCPRcv, p->stream, pnum);
  291.     pbp->csParam.receive.rcvBuff = buffer;
  292.     pbp->csParam.receive.rcvBuffLen = reqdamt;
  293.     
  294.     if (reqdamt<1) {                                /* Drop out if no data */
  295.         returnPB(pbp);
  296.         return(0);
  297.         }
  298.     
  299.     if ((i = PBControl((ParmBlkPtr) pbp, noQcall)) != noError) {
  300.         char temp[100];
  301.         sprintf(temp,"TCPRcv failed (%d)",i);
  302.         putln( temp);
  303.         return(-1);
  304.         }
  305.         
  306.     reqdamt = pbp->csParam.receive.rcvBuffLen;
  307.     if (reqdamt<inQ) {
  308.         netputuev( CONCLASS, CONDATA, pnum);            /* more data to get */
  309.         }
  310.         
  311.     returnPB(pbp);                    /* Trash PB */
  312. #ifdef TESTINGPARMS
  313.     {
  314.         char temp[100];
  315.         sprintf(temp, "NETRead: %d from %d", reqdamt, pnum);
  316.         putln(temp);
  317.     }
  318. #endif TESTINGPARMS
  319.     return(reqdamt);
  320. }
  321.  
  322. /**************************************************************************/
  323. /* 
  324.  *    reclaim( p) -
  325.  *        reclaims buffer space to stream (from pointer p) into the FDS list 
  326.  */
  327.  
  328. reclaim(p)
  329. StreamRPtr p;
  330. {
  331.     int n=0, offset=0;
  332.     
  333.     while (offset < MAX_FDS_ELEMS && p->fds[offset].ptr != 0L) offset++;
  334.     
  335.     if (offset >= MAX_FDS_ELEMS) {
  336.         putln("Couldn't reclaim because offset was too large ");
  337.         return(0);
  338.         }
  339.     for (n=0 ; n<MAX_FDS_ELEMS && offset< MAX_FDS_ELEMS; n++) {
  340.         if (p->exFDS[ n].inuse) {
  341.             p->fds[ offset++]=p->exFDS[ n].fds;
  342.             p->exFDS[ n].inuse = 0;
  343.             }
  344.         }
  345. }
  346.  
  347. /**************************************************************************/
  348. /*
  349.  *     compressfds( fds)
  350.  *        compress an fds data structure to make everyone happy
  351.  */
  352.  
  353. compressfds( fds)
  354. wdsEntry *fds;
  355. {
  356.     int n,m,compressed;
  357.     
  358.     compressed = 0;
  359.     
  360.     while ( !compressed) {
  361.         compressed=1;
  362.         for (n=0; n< MAX_FDS_ELEMS; n++) {                /* Slow Forwards */
  363.             if (fds[n].ptr) {                                /* Do if N exists */
  364.                 for ( m = MAX_FDS_ELEMS -1; m>=0; m--) {    /* Fast Backwards */
  365.                     if (fds[m].ptr && (fds[m].ptr+fds[m].length == fds[n].ptr)) {
  366.                         fds[n].length+=fds[m].length;
  367.                         fds[n].ptr = fds[m].ptr;
  368.                         fds[m].ptr=0L;
  369.                         fds[m].length=0;
  370.                         compressed=0;
  371.                         }
  372. #ifdef CHECKBOTHWAYZ
  373.                     else 
  374.                     if (fds[n].ptr+fds[n].length == fds[m].ptr) {
  375.                         fds[m].length+=fds[n].length;
  376.                         fds[n].ptr=0L;
  377.                         fds[n].length=0;
  378.                         compressed=0;
  379.                         }
  380. #endif CHECKBOTHWAYZ
  381.                     }
  382.                 }
  383.             }
  384.         }
  385.     m=0;n=0;
  386.     
  387.     /* Close the gaps */
  388.     
  389.     while (n+m < MAX_FDS_ELEMS) {
  390.         while (fds[n+m].ptr ==0L && n+m< MAX_FDS_ELEMS) {
  391.             m++;            /* increase gap to valid entry */
  392.             }
  393.         if (n+m<MAX_FDS_ELEMS)
  394.             fds[n]=fds[n+m];
  395.         n++;
  396.         }
  397.     
  398.     /* Get rid of the empty spaces */
  399.     
  400.     n--;        /* for the next loop */
  401.     while (n < MAX_FDS_ELEMS) {
  402.         fds[n].ptr=0; fds[n++].length=0;
  403.         }
  404. }
  405.  
  406. /************************************************************************/
  407. /* netwrite
  408. *  write something into the output queue, netsleep routine will come
  409. *  around and send the data, etc.
  410. *
  411. */
  412. netwrite(pnum,buffer,nsend)
  413.     int pnum,nsend;
  414.     char *buffer;
  415.     {
  416.     StreamRPtr p;
  417.     wdsEntry *swds;
  418.     int remaining, queued, n,m;
  419.     TCPiopb *pbp;
  420.     
  421.     if (pnum < 0)
  422.         return(-2);
  423.  
  424.     if ( (p = streams[pnum]) == NULL)
  425.         return(-2);
  426.     
  427.     if ( !nsend )
  428.         return(0);
  429.         
  430.     swds = getSWDS();
  431.     
  432.     reclaim( p);
  433.     compressfds( p->fds);
  434.  
  435.     n=0; remaining = nsend;
  436.     while (p->fds[n].ptr !=0 && remaining>0 ) {
  437.         swds[n].ptr = p->fds[n].ptr;
  438.         if ( p->fds[n].length > remaining) {
  439.             swds[n].length = remaining;
  440.             p->fds[n].length -= remaining;
  441.             p->fds[n].ptr += remaining;
  442.             remaining=0;
  443.             }
  444.         else {
  445.             swds[n].length =  p->fds[n].length;
  446.             remaining -= p->fds[n].length;
  447.             p->fds[n].length = 0;
  448.             p->fds[n].ptr = 0;
  449.             }
  450.         n++;
  451.         }
  452.     if (n>p->maxFDSused) p->maxFDSused=n;
  453.     
  454.     compressfds( p->fds);
  455.     queued = nsend-remaining;
  456.     
  457.     for (m=0; m<n; m++) {
  458.         memcpy( swds[m].ptr, buffer, swds[m].length);    /* Put data in WDS */
  459.         buffer +=swds[m].length;
  460.         }
  461.     swds[m].ptr =0L;
  462.     swds[m].length=0;
  463.     
  464.     pbp=getPB( TCPd, TCPSend, p->stream, pnum);            /* Make send call */
  465.     pbp->csParam.send.wdsPtr = (Ptr) swds;
  466.     pbp->csParam.send.pushFlag = p->push;
  467.     
  468.     pbp->ioCompletion = (TCPIOCompletionProc) sendComplete;                    /* Completion routine */
  469.  
  470.     p->push=0;
  471.  
  472.     if (PBControl((ParmBlkPtr) pbp, Qcall) != noError) {
  473.         putln("TCPSend failed to Q"); return(-1);
  474.         }
  475.     
  476. #ifdef TESTINGPARMS
  477.     putln("TCP Sent");
  478.     { char temp[100];
  479.         sprintf(temp, "TCP Sent: %d of %d on %d [%d/%d]", queued, nsend, pnum,n,p->maxFDSused);
  480.         putln(temp);
  481.     }
  482. #endif TESTINGPARMS
  483.     return(queued);
  484. }
  485.  
  486. /**************************************************************************/
  487. /*  netpush
  488. *   attempt to push the rest of the data from the queue
  489. *   and then return whether the queue is empty or not (0 = empty)
  490. *   returns the number of bytes in the queue.
  491. */
  492. netpush(pnum)
  493.     int pnum;
  494.     {
  495.     StreamRPtr p;
  496.     TCPiopb *pbp;
  497.     int inQ;
  498.     
  499.     if (pnum < 0)
  500.         return(-2);
  501.  
  502.     if (NULL == (p = streams[pnum]))
  503.         return(-2);
  504.  
  505.     pbp=getPB( TCPd, TCPStatus, p->stream, pnum);            /* Make status call */
  506.     if (PBControl((ParmBlkPtr) pbp, noQcall) != noError) {
  507.         putln("TCPStatus failed(push)"); return(-1);
  508.         }
  509.     inQ = pbp->csParam.status.amtUnackedData;
  510.     returnPB( pbp);
  511.     
  512.     p->push=1;
  513.     
  514.     return(inQ);
  515.  
  516. }    
  517.  
  518. /**************************************************************************/
  519. /*  netqlen
  520. *   return the number of bytes waiting to be read from the incoming queue.
  521. */
  522. netqlen(pnum)
  523.     int pnum;
  524.     {
  525.     StreamRPtr p;
  526.     TCPiopb *pbp;
  527.     int inQ;
  528.     
  529.     if (pnum < 0)
  530.         return(-2);
  531.  
  532.     if (NULL == (p = streams[pnum]))
  533.         return(-2);
  534.  
  535.     pbp=getPB( TCPd, TCPStatus, p->stream, pnum);            /* Make status call */
  536.     if (PBControl((ParmBlkPtr) pbp, noQcall) != noError) {
  537.         putln("TCPStatus failed(qlen)"); return(-1);
  538.         }
  539.     inQ = pbp->csParam.status.amtUnreadData;
  540.     returnPB( pbp);
  541.     
  542.     p->push = 1;
  543.     return(inQ);
  544. }
  545.  
  546. /**************************************************************************/
  547. /*  netroom()
  548. *    return how much room is available in output buffer for a connection
  549. */
  550. netroom(pnum)
  551.     int pnum;
  552.     {
  553.     StreamRPtr p;
  554.     TCPiopb *pbp;
  555.     int inQ,n;
  556.     
  557.     if (pnum < 0)
  558.         return(-2);
  559.  
  560.     if (NULL == (p = streams[pnum]))
  561.         return(-2);
  562.  
  563.     reclaim( p);
  564.     compressfds( p->fds);
  565.  
  566. #ifdef OLDM
  567.     pbp=getPB( TCPd, TCPStatus, p->stream, pnum);            /* Make status call */
  568.     if (PBControl((ParmBlkPtr) pbp, noQcall) != noError) {
  569.         putln("TCPStatus failed(room)"); return(-1);
  570.         }
  571.     inQ = pbp->csParam.status.sendWindow -
  572.                 pbp->csParam.status.amtUnackedData;
  573.     returnPB( pbp);
  574. #else
  575. #pragma unused(pbp)
  576. #endif
  577.  
  578.     inQ = n = 0;
  579.     while (p->fds[n].ptr) {
  580.     
  581.         inQ += p->fds[n].length;                /* add up free list space */
  582.         n++;
  583.         }
  584.  
  585.     return(inQ);
  586. }
  587.  
  588. /**************************************************************************/
  589. /* netsegsize and neterrchange and netsetip and netgetip
  590. *
  591. *  set operating parameters to change them from the default values used.
  592. */
  593.  
  594. netsegsize(newsize)
  595.     int newsize;
  596.     {
  597.     int i;
  598.  
  599.     i = nnsegsize;
  600.     nnsegsize = newsize;
  601.  
  602.     return(i);
  603. }
  604.  
  605. /**************************************************************************/
  606. netquench(newcredit)
  607.     int newcredit;
  608.     {
  609.     int i;
  610.  
  611.     i = nncredit;
  612.     nncredit = newcredit;
  613.  
  614.     return(i);
  615. }
  616.  
  617. /**************************************************************************/
  618. netarptime(t)                    /* dlayer timeout in secs */
  619.     int t;
  620.     {
  621.     nndto = t;
  622. }
  623.  
  624. /**************************************************************************/
  625. void netsetip
  626.   (
  627.     unsigned char *st
  628.   )
  629.     {
  630. /*
  631. *  this is a no-op with the MacTCP driver
  632. */
  633. #pragma unused(st)
  634. }
  635.  
  636. /**************************************************************************/
  637. int netgetip
  638.   (
  639.     unsigned char *st
  640.   )
  641. {
  642.     struct IPParamBlock mypb;
  643.     /* long netmask; */
  644.  
  645.     putln("Attempting getmyipaddr");
  646.     
  647.     memset( &mypb, '\0', sizeof(struct IPParamBlock));    /* Default to all zeros */
  648.     
  649.     mypb.ioCRefNum = TCPd;            /* TCP driver has to be open by now */
  650.     mypb.csCode = ipctlGetAddr;
  651.  
  652.     if (PBControl((ParmBlkPtr) &mypb, noQcall) != noError) {
  653.         putln("Getting my address failed"); 
  654.         return(-1);
  655.         }
  656.     
  657.     memcpy(st, &mypb.ourAddress, 4);    /* copy the address */
  658.     
  659.     /* netmask is here if we want it, too */
  660.     
  661.     return(0);
  662.  
  663. }
  664.  
  665.  
  666. /**************************************************************************/
  667. netsetmask(st)
  668. unsigned char *st;
  669. {
  670.     movebytes(nnmask,st,4);
  671. }
  672.  
  673. /**************************************************************************/
  674. netgetmask(st)
  675. unsigned char *st;
  676. {
  677.     movebytes(st,nnmask,4);
  678. }
  679.  
  680. netfromport(port)            /* next "open" will use this port */
  681. int16 port;
  682. {
  683.     nnfromport = port;
  684.  
  685. }
  686.  
  687. /**************************************************************************/
  688. /*  netest?
  689. *  is a particular session established yet?
  690. *  Returns 0 if the connection is in the established state.
  691. */
  692. netest(pnum)
  693. int pnum;
  694. {
  695.     StreamRPtr p;
  696.     TCPiopb *pbp;
  697.     int inQ;
  698.     
  699.     if (pnum < 0)
  700.         return(-2);
  701.  
  702.     if (NULL == (p = streams[pnum]))
  703.         return(-2);
  704.  
  705.     pbp=getPB( TCPd, TCPStatus, p->stream, pnum);            /* Make status call */
  706.     if (PBControl((ParmBlkPtr) pbp, noQcall) != noError) {
  707.         putln("TCPStatus failed(est)");
  708.         inQ = -1;
  709.         }
  710.     else 
  711.         inQ = pbp->csParam.status.connectionState !=8;
  712.     returnPB( pbp);
  713.     
  714.     return(inQ);
  715.  
  716. }
  717.  
  718. /**************************************************************************/
  719. /*
  720.  * Returns an empty stream
  721.  */ 
  722. makestream()
  723. {
  724.     int    pnum;
  725.     StreamRPtr p;
  726.     TCPiopb *pbp;
  727.     int i;
  728.     
  729.     for ( pnum=0; streams[pnum]!= NULL && pnum<NPORTS; pnum++);
  730.     
  731.     if (pnum >= NPORTS)
  732.         return(-2);
  733.  
  734.     p = streams[pnum] = (StreamRPtr) NewPtr(sizeof(StreamRec));
  735.  
  736.     if ((p->buffer = (char *) NewPtr( TCPBUFSIZ)) == (char *)NULL)
  737.         return(-1);
  738.     if ((p->sbuffer = (char *) NewPtr( TCPBUFSIZ)) == (char *)NULL)
  739.         return(-1);
  740.     
  741.     for (i=0; i<MAX_FDS_ELEMS; i++) {
  742.         p->fds[ i].length =0; p->fds[ i].ptr = 0L;
  743.         p->exFDS[ i].inuse=0; p->exFDS[ i].fds.length=0;p->exFDS[ i].fds.ptr=0L;
  744.         }
  745.     p->fds[0].length = TCPBUFSIZ;
  746.     p->fds[0].ptr = p->sbuffer;
  747.     p->maxFDSused=0;
  748.     
  749.     pbp=getPB( TCPd, TCPCreate, 0, pnum);            /* Make create call */
  750.     pbp->csParam.create.rcvBuff = p->buffer;
  751.     pbp->csParam.create.rcvBuffLen = TCPBUFSIZ;
  752.     pbp->csParam.create.notifyProc = TCPNotify;
  753.     if (PBControl((ParmBlkPtr) pbp, noQcall) != noError) {
  754.         putln("TCPCreate failed"); return(-1);
  755.         }
  756.     
  757.     p->stream = pbp->tcpStream;
  758.     
  759.     putln("Made a new stream");
  760.     returnPB(pbp);
  761.     return(pnum);
  762. }
  763.  
  764. /**************************************************************************/
  765. /*  netlisten
  766. *   Listen to a TCP port number and make the connection automatically when
  767. *   the SYN packet comes in.  The TCP layer will notify the higher layers
  768. *   with a CONOPEN event.  Save the port number returned to refer to this
  769. *   connection.
  770. *
  771. *   usage:   portnum = netlisten(service);
  772. *            int service;
  773. *
  774. */
  775. netlisten(serv)
  776. uint serv;
  777. {
  778.     int    pnum;
  779.     StreamRPtr p;
  780.     TCPiopb *pbp;
  781.  
  782.     pnum = makestream();
  783.  
  784.     if (pnum < 0)
  785.         return(-2);
  786.  
  787.     if (NULL == (p = streams[pnum]))
  788.         return(-2);
  789.  
  790.     pbp=getPB( TCPd, TCPPassiveOpen, p->stream, pnum);            /* Make Listen call */
  791.     
  792.     pbp->csParam.open.localPort = serv;
  793.     pbp->ioCompletion = (TCPIOCompletionProc) openComplete;        /* IO Completion for open */
  794.     
  795.     if (PBControl((ParmBlkPtr) pbp, Qcall) != noError) {
  796.         putln("TCPListen failed"); return(-1);
  797.         }
  798.         
  799.     return(pnum);
  800. }
  801.  
  802. /***********************************************************************/
  803. /*  netgetftp
  804. *  Provides the information that ftp needs to open a stream back to the
  805. *  originator of the command connection.  The other side's IP number
  806. *  and the port numbers to be used to calculate the default data connection
  807. *  number.  Returns values in an integer array for convenient use in 
  808. *  PORT commands.
  809. */
  810. netgetftp(a,pnum)
  811. int a[];
  812. int pnum;
  813. {
  814.     StreamRPtr p;
  815.     TCPiopb *pbp;
  816.     long temp;
  817.     
  818.     if (pnum < 0)
  819.         return(-2);
  820.  
  821.     if (NULL == (p = streams[pnum]))
  822.         return(-2);
  823.  
  824.     pbp=getPB( TCPd, TCPStatus, p->stream, pnum);            /* Make status call */
  825.     if (PBControl((ParmBlkPtr) pbp, noQcall) != noError) {
  826.         putln("TCPStatus failed(getftp)"); return(-1);
  827.         }
  828.  
  829.     temp      = pbp->csParam.status.remoteHost;
  830.     a[0]= (temp>>24) & 0xff;
  831.     a[1]= (temp>>16) & 0xff;
  832.     a[2]= (temp>> 8) & 0xff;
  833.     a[3]= (temp    ) & 0xff;
  834.     temp    = pbp->csParam.status.localPort;
  835.     a[4]= (temp>> 8) & 0xff;
  836.     a[5]= (temp    ) & 0xff;
  837.     temp    = pbp->csParam.status.remotePort;
  838.     a[6]= (temp>> 8) & 0xff;
  839.     a[7]= (temp    ) & 0xff;
  840.  
  841.     returnPB( pbp);
  842. }
  843.  
  844.  
  845. /**************************************************************************/
  846. /*  netxopen
  847. *   Open a network socket for the user.
  848. *
  849. */
  850. int netxopen
  851.   (
  852.     uint32 *machine,
  853.     uint service,
  854.     uint rto,
  855.     uint mtu,
  856.     uint mseg,
  857.     uint mwin
  858.   )
  859. {
  860. #pragma unused(rto, mtu, mseg, mwin)
  861.     int    pnum;
  862.     StreamRPtr p;
  863.     TCPiopb *pbp;
  864.     char temp[100];
  865.     
  866.     pnum = makestream();
  867.  
  868.     if (pnum < 0)
  869.         return(-2);
  870.  
  871.     if (NULL == (p = streams[pnum]))
  872.         return(-2);
  873.  
  874.     pbp=getPB( TCPd, TCPActiveOpen, p->stream, pnum);            /* Make Listen call */
  875.     
  876.     pbp->csParam.open.remoteHost = *machine;            /* IP # */
  877.     pbp->csParam.open.remotePort = service;                /* Port */
  878.     pbp->csParam.open.localPort = nnfromport;            /* My Port */
  879.     nnfromport=0;                                            /* Next one is random */
  880.     
  881.     pbp->ioCompletion = (TCPIOCompletionProc) openComplete;    /* IO Completion for open */
  882.     
  883.     if (PBControl((ParmBlkPtr) pbp, Qcall) != noError) {
  884.         putln("TCPOpen failed(Active)"); return(-1);
  885.         }
  886.     sprintf(temp,"TCPOpen on %d",pnum);
  887.     putln(temp);
  888.     return(pnum);
  889. }
  890.  
  891. /**************************************************************************/
  892. /*  netopen
  893. *   Netopen is a cheap way to open a connection without looking up any
  894. *   machine information.  Uses suitable default values for everything.
  895. */
  896. netopen(s,tport)
  897. unsigned char *s;
  898. uint tport;
  899. {
  900.  
  901.     return(netxopen((uint32 *) s,tport,MINRTO,TSENDSIZE,DEFSEG,DEFWINDOW));
  902. }
  903.  
  904.  
  905. /**************************************************************************/
  906. /* netclose
  907. *  Do appropriate actions to return connection state to SCLOSED which
  908. *  enables the memory for that port to be reused.
  909. *
  910. *    Specifically:
  911. *        o If status is closed, then release the data structures
  912. *        o If status is not close, perform bkgrd close which generates CLOSEDONE,
  913. *            which should make the session layer call us again
  914. */
  915. int netclose
  916.   (
  917.     int pnum
  918.   )
  919. {
  920.     StreamRPtr p;
  921.     TCPiopb *pbp;
  922.     int errorCode=0;
  923.     int status;
  924.     char temp[50];
  925.     static short count=0;
  926.     
  927.     if (pnum < 0 || pnum > NPORTS)            /* is a valid port? */
  928.         return(-1);
  929.  
  930.     if ((p = streams[pnum]) == NULL)             /* nothing there */
  931.         return (1);
  932.  
  933.     pbp=getPB( TCPd, TCPStatus, p->stream, pnum);            /* Make status call */
  934.     if ((errorCode = PBControl((ParmBlkPtr) pbp, noQcall)) != noError) {
  935.         if ( errorCode == invalidStreamPtr) {
  936.             putln("TCPStatus failed because of bad stream pointer (close)");
  937.             return(-1);
  938.             }
  939.         else
  940.             {
  941.             status=0;
  942.             count =0;
  943.             }
  944.         }
  945.     else 
  946.         {
  947.         status = pbp->csParam.status.connectionState;            /* The connection Status */
  948.         if (count++ ==10) status=count =0;
  949.         }
  950.  
  951. /* */
  952.  
  953.     sprintf(temp,"the error Code is %i",(int)errorCode);
  954.     putln(temp);
  955.  
  956.     if (status < 18 && status >2 ) {                            /* We aren't closed yet ! */
  957.         char temp[50];
  958.         sprintf(temp, "TCPClose being attempted state ...[%d]",status);    /* Prolly because outstanding close */
  959.         putln(temp);
  960.         clearPB( pbp, TCPd, TCPClose, p->stream, pnum);            /* Make Close call */
  961.         pbp->ioCompletion = (TCPIOCompletionProc) closeComplete; /* IO Completion for close */
  962.         if ((errorCode=PBControl((ParmBlkPtr) pbp, Qcall)) != noError) {
  963.             char temp[50];
  964.             sprintf(temp, "TCPClose failed...[%d]",errorCode);    /* Prolly because outstanding close */
  965.             putln(temp);
  966.             putln("we have an error");
  967.             return (errorCode); /* */
  968.             }
  969.  
  970.         return (0);                                            /* Return with OK */
  971.         }
  972.  
  973.     /* IF we got here, we must be at closed state, so free memory */
  974.  
  975.     putln("TCP Being Released...... ");
  976.     clearPB( pbp,TCPd, TCPRelease, p->stream, pnum);            /* Make Release call */
  977.     if (PBControl((ParmBlkPtr) pbp, noQcall) != noError) {
  978.         putln("TCPRelease failed"); return(-1);
  979.         }
  980.     
  981.     DisposPtr( p->buffer);                /* Free Receive Buffer */
  982.     DisposPtr( p->sbuffer);                /* Free Send Buffer */
  983.     DisposPtr((Ptr) p);                    /* Free Stream Structure */
  984.     streams[pnum]=0L;
  985.  
  986.     returnPB(pbp);
  987.     return(0);
  988. }
  989.  
  990. /**************************************************************************/
  991. /* netabort
  992. *    Nuke the connection, NOW!
  993. */
  994. netabort(pnum)
  995. int pnum;
  996. {
  997.     StreamRPtr p;
  998.     TCPiopb *pbp;
  999.     int errorCode=0;
  1000.  
  1001.     if (pnum < 0 || pnum > NPORTS)            /* is a valid port? */
  1002.         return(-1);
  1003.  
  1004.     if ((p = streams[pnum]) != NULL) {            /* something there */
  1005.         pbp=getPB( TCPd, TCPAbort, p->stream, pnum);            /* Make Close call */
  1006.         if ((errorCode=PBControl((ParmBlkPtr) pbp, noQcall)) != noError) {
  1007.             char temp[50];
  1008.             sprintf(temp, "TCPAbort failed...[%d]",errorCode);
  1009.             putln(temp);
  1010.             }
  1011.         clearPB( pbp,TCPd, TCPRelease, p->stream, pnum);            /* Make Close call */
  1012.         if (PBControl((ParmBlkPtr) pbp, noQcall) != noError) {
  1013.             putln("TCPRelease failed"); return(-1);
  1014.             }
  1015.         }
  1016.     else
  1017.         return(1);
  1018.     
  1019.     DisposPtr( p->buffer);                /* Free Receive Buffer */
  1020.     DisposPtr( p->sbuffer);                /* Free Send Buffer */
  1021.     DisposPtr((Ptr) p);                    /* Free Stream Structure */
  1022.     streams[pnum]=0L;
  1023.  
  1024.     returnPB(pbp);
  1025.     return(0);
  1026. }
  1027.  
  1028. /**************************************************************************/
  1029. /*  netinit
  1030. *   Calls all of the various initialization routines that set up queueing
  1031. *   variables, static values, reads configuration files, etc.
  1032. */
  1033.  
  1034. int netinit
  1035.   (
  1036.     void
  1037.   )
  1038. {
  1039.     int i;
  1040. extern Cursor *normcurs;
  1041.     OSErr rc;
  1042.     
  1043.     for (i=0; i<NPORTS;i++)
  1044.         streams[i]= (StreamRPtr) 0;
  1045.         
  1046.     for (i=0; i<NPORTS;i++)
  1047.         uport[i]= (UDPRPtr) 0;
  1048.     
  1049.     rc = opendriver(".IPP",&TCPd);
  1050.     if (rc != noError) {
  1051.         SetCursor(normcurs);
  1052.         putln( "Couldn't open IP driver ");
  1053.         OtherError("Error opening TCP drivers.","Possibly no dynamic addressing");
  1054.         tcpquit(rc);
  1055.         }
  1056.         
  1057.     return(0);                /* set up empty packets */
  1058. }
  1059.  
  1060. /**************************************************************************/
  1061. int UDPfindport( port)
  1062. int port;
  1063. {
  1064.     int pnum=0;
  1065.     
  1066.     while (pnum<NPORTS &&
  1067.             ( uport[pnum] ==(UDPRPtr)0L || port !=uport[pnum]->port))
  1068.         pnum++;
  1069.     if (pnum >=NPORTS)
  1070.         return(-1);
  1071.     else
  1072.         return(pnum);
  1073. }
  1074.  
  1075. /**************************************************************************/
  1076. /*
  1077.  * netuclose( port)             - close the udp port 
  1078.  */
  1079.  
  1080. netuclose( port)
  1081. int port;
  1082. {
  1083.     UDPRPtr p;
  1084.     UDPiopb *pbp;
  1085.     int pnum;
  1086.     
  1087.     pnum= UDPfindport( port);
  1088.     
  1089.     if (pnum<0)
  1090.         return(-1);
  1091.     
  1092.     p=uport[pnum];
  1093.     
  1094.     pbp = getUPB( TCPd, UDPRelease, p->stream, 0);
  1095.     if (PBControl((ParmBlkPtr) pbp, noQcall) != noError) {
  1096.         putln("UDPClose failed"); return(-1);
  1097.         }
  1098.     DisposPtr( p->buffer);
  1099.     DisposPtr((Ptr) uport[pnum]);
  1100.     uport[pnum]=0;                /* use me again */
  1101.     
  1102.     returnPB( pbp);
  1103. }
  1104.  
  1105. /*************************************************************************/
  1106. /*  netshut
  1107. *   Close all the connections and turn off the hardware.
  1108. */
  1109. netshut()
  1110.     {
  1111.     int i;
  1112.  
  1113.     for (i=0; i < NPORTS ; i++) 
  1114.         if (streams[i] != (StreamRPtr) NULL)
  1115.             netabort(i);                        /* Prolly should abort */
  1116.     for (i=0; i < NPORTS ; i++) 
  1117.         if (uport[i] != (UDPRPtr) NULL)
  1118.             netuclose(uport[i]->port);            /* Shut down UDP too... */
  1119. #ifdef SAFE
  1120.     CloseDriver( TCPd);
  1121. #endif SAFE
  1122. }
  1123.  
  1124. /**************************************************************************/
  1125. int findbystream( streamPtr)
  1126. StreamPtr streamPtr;
  1127. {
  1128.     int pnum=0;
  1129.     
  1130.     while (pnum<NPORTS &&
  1131.             ( (streams[pnum] ==(StreamRPtr)0L) || (streamPtr !=streams[pnum]->stream)))
  1132.         pnum++;
  1133.     if (pnum >=NPORTS)
  1134.         return(-1);
  1135.     else
  1136.         return(pnum);
  1137. }
  1138.  
  1139.  
  1140. /**************************************************************************/
  1141. pascal void TCPNotify( streamPtr, code, uptr, terminReason, icmpMsg)
  1142. StreamPtr streamPtr;
  1143. unsigned short /*enum  TCPEventCode*/ code;
  1144. unsigned short /*enum  TCPTerminationReason*/ terminReason;
  1145. struct ICMPReport *icmpMsg;
  1146. Ptr uptr;   /* user data pointer */
  1147. {
  1148. #pragma unused(uptr, terminReason, icmpMsg)
  1149.     StreamRPtr p;
  1150.     int pnum;
  1151.     
  1152.     pnum = findbystream(streamPtr);
  1153.     
  1154.     if (pnum < 0 || (p = streams[pnum]) == 0L)
  1155.         return;
  1156.     
  1157.     switch( code) {
  1158.         case TCPTerminate:
  1159.         case TCPClosing:
  1160.             netputevent(CONCLASS, CONCLOSE, pnum);
  1161.             break;
  1162.         case TCPULPTimeout:
  1163.             netputevent(CONCLASS, CONFAIL, pnum);
  1164.             break;
  1165.         case TCPDataArrival:
  1166.         case TCPUrgent:
  1167.             netputuev(CONCLASS, CONDATA, pnum);
  1168.             break;
  1169.         case TCPICMPReceived:
  1170.         default:
  1171.             break;
  1172.         }
  1173.     return;
  1174. }
  1175.  
  1176. /*************************************************************************/
  1177. /*  netopen2
  1178. *   Send out repeat SYN on a connection which is not open yet
  1179. *   Checks, and only sends one if needed.
  1180. *   Returns 1 if the state is still SYNS and 0 if the connection has proceeded.
  1181. *   The timing is all handled at a higher layer.
  1182. */
  1183. int netopen2
  1184.   (
  1185.     int pnum
  1186.   )
  1187. {
  1188.     return( netest(pnum));
  1189. }
  1190.  
  1191. /**************************************************************************/
  1192. long openComplete( pbp)
  1193. TCPiopb *pbp;
  1194. {
  1195.     StreamRPtr p;
  1196.     int pnum;
  1197.     
  1198.     pnum= findbystream(pbp->tcpStream);
  1199.     
  1200.     if (pnum < 0 || (p = streams[pnum]) == 0L) 
  1201.         return(-1);
  1202.         
  1203.     if (pbp->ioResult !=noError) 
  1204.         netputevent(CONCLASS, CONFAIL, pnum);            /* Failure ... */
  1205.     else 
  1206.         netputevent(CONCLASS, CONOPEN, pnum);            /* Success ! */
  1207.  
  1208.     returnPB( pbp);
  1209.     return(0);
  1210. }
  1211.  
  1212. /**************************************************************************/
  1213. /*
  1214.  *    giveback( p, wds) -
  1215.  *        gives WDS entries back to the stream by putting them in the 
  1216.  *        mutually exclusive buffer.
  1217.  *    p -> stream
  1218.  *    wds -> wds array
  1219.  */
  1220. giveback( p, wds)
  1221. StreamRPtr p;
  1222. wdsEntry *wds;
  1223. {
  1224.     int n=0, m=0;
  1225.     
  1226.     while ( n< MAX_SWDS_ELEMS && wds[n].ptr !=0L) {
  1227.         while (m< MAX_FDS_ELEMS && p->exFDS[ m].inuse) m++;
  1228.         if (m> MAX_FDS_ELEMS)
  1229.             return(-1);                /* No room in the RECLAIMation center */
  1230.         else {
  1231.             p->exFDS[ m].inuse =1;
  1232.             p->exFDS[ m].fds = wds[n];
  1233.             m++;
  1234.             }
  1235.         n++;
  1236.         }
  1237. }
  1238.  
  1239.  
  1240. /**************************************************************************/
  1241. long sendComplete( pbp)
  1242. TCPiopb *pbp;
  1243. {
  1244.     StreamRPtr p;
  1245.     int pnum;
  1246.     wdsEntry *swds;
  1247.     int i=0,j=0;
  1248.     
  1249.     (Ptr) swds = pbp->csParam.send.wdsPtr;
  1250.     
  1251.     pnum= findbystream(pbp->tcpStream);
  1252.     if (pnum < 0 || (p = streams[pnum]) == 0L)
  1253.         return(-1);
  1254.  
  1255.     returnSWDS( swds);
  1256.     returnPB( pbp);
  1257.  
  1258.     giveback( p, pbp->csParam.send.wdsPtr);            /* Give this back.... NOW */
  1259.     
  1260.     return(0);
  1261. }
  1262.  
  1263.  
  1264. /**************************************************************************/
  1265. long closeComplete( pbp)
  1266. TCPiopb *pbp;
  1267. {
  1268.     StreamRPtr p;
  1269.     int pnum;
  1270.     
  1271.     pnum= findbystream(pbp->tcpStream);
  1272.     
  1273.     if (pnum < 0 || (p = streams[pnum]) == 0L)
  1274.       {
  1275.         netputevent(SCLASS, CLOSEDONE+1, pnum);
  1276.         return(-1);
  1277.       }
  1278.         
  1279.     if (pbp->ioResult !=noError) 
  1280.         netputevent(SCLASS, CLOSEDONE+1, pnum);
  1281.     else 
  1282.         netputevent(SCLASS, CLOSEDONE, pnum);            /* Success ! */
  1283.  
  1284.     returnPB( pbp);
  1285.     return(0);
  1286. }
  1287.  
  1288.  
  1289.  
  1290. /*****************************************************************************
  1291.  *
  1292.  * Here lie the awful UDP routines, I put them here for the drivers from Apple.
  1293.  *
  1294.  */
  1295.  
  1296.  int UDPlisten =0;                /* what port the old routines listen for */
  1297.  
  1298.  
  1299. /****************************************************************************/
  1300. /*                    New UDP routines....                                    */
  1301. /****************************************************************************/
  1302.  
  1303. /**************************************************************************/
  1304. makeuport( port)
  1305. int port;
  1306. {
  1307.     int    pnum;
  1308.     UDPRPtr p;
  1309.     UDPiopb *pbp;
  1310.     int i;
  1311.     
  1312.     for ( pnum=0; uport[pnum]!= NULL && pnum<NPORTS; pnum++);
  1313.     
  1314.     if (pnum >= NPORTS)
  1315.         return(-2);
  1316.  
  1317.     p = uport[pnum] = (UDPRPtr) NewPtr(sizeof(UDPRec));
  1318.  
  1319.     if ((p->buffer = (char *) NewPtr( UDPBUFSIZ)) == (char *)NULL)
  1320.         return(-1);
  1321.     
  1322.     
  1323.     pbp=getUPB( TCPd, UDPCreate, 0, pnum);            /* Make create call */
  1324.     
  1325.     pbp->csParam.create.rcvBuff  = p->buffer;
  1326.     pbp->csParam.create.rcvBuffLen= UDPBUFSIZ;
  1327.     pbp->csParam.create.notifyProc     = UDPNotify;
  1328.     pbp->csParam.create.localPort = port;
  1329.     
  1330.     if ((i=PBControl((ParmBlkPtr) pbp, noQcall)) != noError) {
  1331.         char temp[50];
  1332.         sprintf(temp, "UDPCreate failed (%d)",i);
  1333.         putln(temp);
  1334.         return(-1);
  1335.         }
  1336.     else {
  1337.         char temp[50];
  1338.         sprintf(temp, "UDPCreate successfull on %d(%d) [%x]",port,pnum,pbp->udpStream);
  1339.         putln(temp);
  1340.         }
  1341.     
  1342.     p->stream = pbp->udpStream;
  1343.     p->port = port;
  1344.     
  1345.     putln("Made a new UPORT");
  1346.     returnPB(pbp);
  1347.     return(pnum);
  1348. }
  1349.  
  1350. /**************************************************************************/
  1351. /*
  1352.  * netuopen (port)             - open the udp port "Port"
  1353.  */
  1354.  
  1355. netuopen(port)
  1356. int port;
  1357. {
  1358.     return(makeuport( port));
  1359. }
  1360.  
  1361. /**************************************************************************/
  1362. /*
  1363.  *    netuget( port, buffer,len, who,where)
  1364.  *                    - read up to len bytes from port port into buffer buffer, noting
  1365.  *                        who it was from and where....
  1366.  */
  1367.  
  1368. netuget( port, buffer, len, who, where)
  1369. int port, len;
  1370. int *who, *where;
  1371. char *buffer;
  1372. {
  1373. #pragma unused(who, where)
  1374.     int pnum, length;
  1375.     UDPRPtr p;
  1376.     UDPiopb *pbp;
  1377.     
  1378.     pnum= UDPfindport( port);
  1379.     
  1380.     if (pnum<0)
  1381.         return(-1);
  1382.     
  1383.     p=uport[pnum];
  1384.     
  1385.     pbp= getUPB( TCPd, UDPRead, p->stream, 0);
  1386.     pbp->csParam.receive.timeOut = 1;                            /* time out at one sec. */
  1387.     
  1388.     if (PBControl((ParmBlkPtr) pbp, noQcall) != noError) {
  1389.         putln("UDPRead failed"); return(-1);
  1390.         }
  1391.     
  1392.     length = pbp->csParam.receive.rcvBuffLen;                /* look how BIG it is */
  1393.     length = length > len ? len:length;
  1394.     
  1395.     memcpy( buffer, pbp->csParam.receive.rcvBuff,length);
  1396.     
  1397.     pbp->csCode = UDPBfrReturn;                                /* Let my buffer go.. */
  1398.     if (PBControl((ParmBlkPtr) pbp, noQcall) != noError) {
  1399.         putln("UDPReturn failed"); return(-1);
  1400.         }
  1401.         
  1402.     returnPB( pbp);
  1403.     
  1404.     return(length);
  1405. }
  1406.  
  1407. /**************************************************************************/
  1408. netuput( machine, port, myport, buffer, n)
  1409. long *machine;
  1410. char *buffer;
  1411. int port, myport;
  1412. int n;
  1413. {
  1414.     wdsEntry wds[2];
  1415.     UDPRPtr p;
  1416.     UDPiopb *pbp; int pnum;
  1417.     
  1418.     pnum= UDPfindport( myport);
  1419.     
  1420.     if (pnum<0)
  1421.         return(-1);
  1422.     
  1423.     p=uport[pnum];
  1424.     
  1425.     pbp= getUPB( TCPd, UDPWrite, p->stream, 0);
  1426.     pbp->csParam.send.remoteHost = *machine;
  1427.     pbp->csParam.send.remotePort = port;
  1428.     pbp->csParam.send.checkSum   = 1;                    /* Do do that checksum that you do so well */
  1429.     pbp->csParam.send.wdsPtr = (Ptr) wds;
  1430. /*    pbp->csParam.send.remoteHost = *machine;    /* BYU - not needed, done above. */
  1431.     
  1432.     wds[0].ptr = buffer;
  1433.     wds[0].length=n;
  1434.     wds[1].ptr = (char *) 0L; wds[1].length=0;
  1435.     
  1436.     if (PBControl((ParmBlkPtr) pbp, noQcall) != noError) {
  1437.         putln("UDPReturn failed"); return(-1);
  1438.         }
  1439.         
  1440.     returnPB( pbp);
  1441.     return(0);
  1442. }
  1443.  
  1444.  
  1445. /****************************************************************************/
  1446. /*  neturead
  1447. *   get the data from the UDP buffer
  1448. *   Returns the number of bytes transferred into your buffer, -1 if none here
  1449. *   This needs work.
  1450. */
  1451. int neturead
  1452.   (
  1453.     char *buffer
  1454.   )
  1455. {
  1456.     int who, where;
  1457.     
  1458.     if (!UDPlisten)
  1459.         return(-1);
  1460.         
  1461.     return( netuget( UDPlisten, buffer, 512, &who, &where));
  1462. }
  1463.  
  1464. /***************************************************************************/
  1465. /*  netulisten
  1466. *   Specify which UDP port number to listen to.
  1467. *   Can only listen to one at a time.
  1468. */
  1469. int netulisten
  1470.   (
  1471.     int port
  1472.   )
  1473. {
  1474.     char temp[50];
  1475.     int pnum;
  1476.  
  1477.     
  1478.     sprintf( temp, "UDP listening on ....%d", port);
  1479.     putln(temp);
  1480.     
  1481.     UDPlisten = port;
  1482.     
  1483.     if ( (pnum=UDPfindport( port))<0)
  1484.         pnum= netuopen(port);
  1485.     
  1486.     return (pnum);
  1487. }
  1488.  
  1489. /***************************************************************************/
  1490. /*  netusend
  1491. *   send some data out in a UDP packet
  1492. *   uses the preinitialized data in the port packet ulist.udpout
  1493. *   
  1494. *   returns 0 on okay send, nonzero on error
  1495. */
  1496. void netusend
  1497.   (
  1498.     unsigned char *machine,
  1499.     unsigned int port,
  1500.     unsigned int retport,
  1501.     unsigned char *buffer,
  1502.     int n
  1503.   )
  1504. {
  1505.     /* find if port is open */
  1506.     if ( UDPfindport( retport)<0)
  1507.         netuopen(retport);
  1508.     
  1509.     /* Send data */
  1510.     netuput( machine, port, retport, buffer,n);
  1511. }
  1512.  
  1513. /**************************************************************************/
  1514. int ufindbystream( streamPtr)
  1515. StreamPtr streamPtr;
  1516. {
  1517.     int pnum=0;
  1518.     
  1519.     while (pnum<NPORTS &&
  1520.             ( uport[pnum] ==(UDPRPtr)0L || streamPtr !=uport[pnum]->stream))
  1521.         pnum++;
  1522.     if (pnum >=NPORTS)
  1523.         return(-1);
  1524.     else
  1525.         return(pnum);
  1526. }
  1527.  
  1528. /**************************************************************************/
  1529. pascal void UDPNotify( streamPtr, code, uptr, icmpMsg)
  1530. StreamPtr streamPtr;
  1531. unsigned short code;
  1532. struct ICMPReport *icmpMsg;
  1533. Ptr uptr;   /* user data */
  1534. {
  1535. #pragma unused(uptr, icmpMsg)
  1536.     UDPRPtr p;
  1537.     int pnum;
  1538.     
  1539.     pnum= ufindbystream(streamPtr);
  1540.     
  1541.     if (pnum < 0 || (p = uport[pnum]) == 0L)
  1542.         return;
  1543.     
  1544.     switch( code) {
  1545.         case UDPDataArrival:
  1546.             netputuev(USERCLASS,UDPDATA,p->port);        /* post that it is here */
  1547.         default:
  1548.             break;
  1549.         }
  1550.     return;
  1551. }
  1552.  
  1553. void netconfig
  1554.   (
  1555.     char *hardware
  1556.   )
  1557. {
  1558. #pragma unused(hardware)
  1559.     putln("I'm a driver TCP, I don't need hardware.....");
  1560.     initipnum(0);
  1561. }
  1562.  
  1563. void netarpme
  1564.   (
  1565.     char *s
  1566.   )
  1567. {
  1568. #pragma unused(s)
  1569.     putln("Drivers don't need arps, either.");
  1570. }
  1571.  
  1572. netsetgate(s)
  1573. char *s;
  1574. {
  1575. #pragma unused(s)
  1576.     putln("Yeah, right....");
  1577.     return
  1578.         0;
  1579. }
  1580.  
  1581. int netgetrarp
  1582.   (
  1583.     void
  1584.   )
  1585. {
  1586.     putln("RARP handled above me....");
  1587.     return
  1588.         0;
  1589. }
  1590.  
  1591. uint8 *getdlayer()
  1592. {
  1593.     putln("This shouldn't be called...");
  1594.     return(0L);
  1595. }
  1596.  
  1597. tcpsend()
  1598. {
  1599. }
  1600.  
  1601. demux()
  1602. {
  1603.     return(0);
  1604. }
  1605.  
  1606. /*************************************************************************/
  1607. /* neteventinit
  1608. *  load up the pointers for the event queue
  1609. *  makes a circular list to follow, required for error messages
  1610. */
  1611. void neteventinit
  1612.   (
  1613.     void
  1614.   )
  1615.     {
  1616.     int i;
  1617.  
  1618.     for (i=0; i < NEVENTS; i++)
  1619.         nnq[i].next = i+1;
  1620.  
  1621.     nnq[NEVENTS-1].next = -1;
  1622.  
  1623.     nnefirst = 0;
  1624.     nnelast = 0;
  1625.     nnefree = 1;
  1626. }
  1627.  
  1628. getATaddress()
  1629. {
  1630. }
  1631.  
  1632. KIPfindgate()
  1633. {
  1634. }
  1635.  
  1636. KIPgetns()
  1637. {
  1638. }
  1639.  
  1640. KIPgetdynam()
  1641. {
  1642. }
  1643.  
  1644. KIPregister()
  1645. {
  1646. }
  1647.